package edu.umn.msse.farside.FourH.services.impl;

import edu.umn.msse.farside.FourH.services.VolunteerService;
import edu.umn.msse.farside.FourH.domain.Volunteer;
import edu.umn.msse.farside.FourH.exceptions.DuplicateVolunteerException;
import edu.umn.msse.farside.FourH.exceptions.InvalidEmailException;
import edu.umn.msse.farside.FourH.exceptions.CorruptedDataException;
import org.springframework.orm.jpa.support.JpaDaoSupport;

import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * User: Farside
 * Date: Feb 6, 2009
 * To change this template use File | Settings | File Templates.
 */
public class VolunteerServiceImpl extends JpaDaoSupport implements VolunteerService
{
    private static final String EMAIL_PATTERN1 = ".+@.+\\.[a-z]+";

    /**
     * create a new volunteer account in the system
     * @param volunteer
     */
    public void addVolunteer(Volunteer volunteer)
    {
        if (volunteer.getId() != null)
        {
            throw new IllegalArgumentException("Not a new volunteer.");
        }

        if (!validEmail(volunteer.getEmail()))
        {
            throw new InvalidEmailException();
        }

        if (findVolunteer(volunteer.getEmail()) != null)
        {
            throw new DuplicateVolunteerException();
        }

        if (volunteer.getPassword() == null)
        {
            volunteer.setPassword(generateRandomString());
        }
        getJpaTemplate().persist(volunteer);
        getJpaTemplate().flush();
    }

    /**
     * Retrieve a volunteer account
     *
     * @param id
     * @return a volunteer account
     */
    public Volunteer getVolunteer(Long id)
    {
        return getJpaTemplate().find(Volunteer.class, id);
    }

    /**
     * Retrieve a volunteer account
     *
     * @param email
     * @return a volunteer account
     */
    public Volunteer findVolunteer(String email)
    {
        List<Volunteer> list = getJpaTemplate().find("from Volunteer v where v.email = ?", email);
        if (list.isEmpty())
        {
            // There is no volunteer with the specified email
            return null;
        }

        if (list.size() > 1)
        {
            // We are not supposed to have more than one record for one email
            throw new CorruptedDataException();
        }

        return list.get(0);
    }

    /**
     * Update the email address, password, first name, and last name of a volunteer account
     *
     * @param volunteer the volunteer account to be updated
     */
    public void updateVolunteer(Volunteer volunteer)
    {
        if (volunteer == null || volunteer.getId() == null)
        {
            throw new IllegalArgumentException();
        }

        if (!validEmail(volunteer.getEmail()))
        {
            throw new InvalidEmailException();
        }

        Volunteer dbVolunteer = findVolunteer(volunteer.getEmail());
        if (dbVolunteer != null)
        {
            // Make sure the update does not introduce duplicate email
            if (!dbVolunteer.getId().equals(volunteer.getId()))
            {
                throw new DuplicateVolunteerException();
            }
        }

        getJpaTemplate().merge(volunteer);
        getJpaTemplate().flush();
    }

    /**
     * delete a volunteer
     *
     * @param email
     */
    public void deleteVolunteer(String email)
    {
        Volunteer volunteer = findVolunteer(email);
        if (volunteer != null)
        {
            getJpaTemplate().remove(volunteer);
        }
        getJpaTemplate().flush();
    }

    /**
     * Validates a user account by email and password
     *
     * @param email
     * @param password
     * @throws SecurityException
     */
    public boolean authenticate(String email, String password)
    {
        Volunteer user = findVolunteer(email);

        if (user == null) return false;

        if (password.equals(user.getPassword())) return true;

        return false;
    }

    /**
     * Reset the user's password to a randomly generated password
     *
     * @param volunteer
     * @return
     */
    public void resetPassword(Volunteer volunteer)
    {
        volunteer.setPassword(generateRandomString());
        updateVolunteer(volunteer);
    }

    private static String generateRandomString()
    {
        Random r = new Random();
        return Long.toString(Math.abs(r.nextLong()), 36);
    }

    private static boolean validEmail(String email)
    {
        //Set the email pattern string
        Pattern p = Pattern.compile(EMAIL_PATTERN1);

        //Match the given string with the pattern
        Matcher m = p.matcher(email);

        //check whether match is found
        return m.matches();
    }
}
